home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / util / gnu / oleo_src.lha / src / byte_compile.c < prev    next >
C/C++ Source or Header  |  1992-08-13  |  24KB  |  865 lines

  1. /*    Copyright (C) 1990 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 1, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "funcdef.h"
  20.  
  21. #include <stdio.h>
  22.  
  23. #define obstack_chunk_alloc ck_malloc
  24. #define obstack_chunk_free free
  25. #include "obstack.h"
  26.  
  27. #include "sysdef.h"
  28.  
  29. #include "global.h"
  30. #include "node.h"
  31. #include "eval.h"
  32.  
  33. /* should be struct var *, but we're cheating */
  34. extern void add_var_ref EXT1(void *);
  35.  
  36. static void add_backpatch EXT2(unsigned, unsigned);
  37.  
  38. struct backpatch {
  39.     unsigned from,to;
  40. };
  41.  
  42. static struct backpatch *patches;
  43. static int patches_allocated;
  44. static int patches_used;
  45. static VOIDSTAR fn_stack;
  46. static VOIDSTAR str_stack;
  47.  
  48. struct obstack tmp_mem;
  49. VOIDSTAR tmp_mem_start;
  50.  
  51. extern double atan2 EXT2(double,double);
  52. extern double hypot EXT2(double,double);
  53. extern double floor EXT1(double);
  54. extern double cos EXT1(double);
  55. extern double to_int EXT1(double);
  56. extern double dtr EXT1(double);
  57. extern double rtd EXT1(double);
  58. extern double exp EXT1(double);
  59. extern double log10 EXT1(double);
  60. extern double sin EXT1(double);
  61. extern double sqrt EXT1(double);
  62. extern double tan EXT1(double);
  63.  
  64. extern double acos EXT1(double);
  65. extern double asin EXT1(double);
  66. extern double atan EXT1(double);
  67. extern double ceil EXT1(double);
  68.  
  69. #define V (void(*)())
  70.  
  71. /* These have to go in some file or other, so it is stuck in here (for now).
  72.  */
  73. struct function the_funs[] = {
  74. { 0,         X_A0,        "",     0,        "<END>" },
  75. { 0,         X_A0,        "",     0,        "<DUMMY1>" },
  76.  
  77. { C_IF|R|INF(1), X_A1|X_J,  "D",    0,        "?" },
  78. { C_IF|R|INF(1), X_A1|X_JL, "D",    0,        "?" },
  79. { C_IF,         X_A1|X_J,  "D",    0,        "if" },
  80. { C_IF,         X_A1|X_JL, "D",    0,        "if" },
  81. { C_ANDOR,     X_A1|X_J,  "D",    0,        "and" },
  82.     /* { C_ANDOR|L|INF(3), X_A1, "DD", 0,        "&" }, */
  83. { C_ANDOR,     X_A1|X_JL, "D",    0,        "and" },
  84.     /* { C_ANDOR|L|INF(3), X_A1, "DD", 0,        "&" }, */
  85. { C_ANDOR,     X_A1|X_J,  "D",    0,        "or" },
  86.     /* { C_ANDOR|L|INF(2), X_A1, "DD", 0,        "|" }, */
  87. { C_ANDOR,     X_A1|X_JL, "D",    0,        "or" },
  88.     /* { C_ANDOR|L|INF(2), X_A1, "DD", 0,        "|" }, */
  89. { C_STR,     X_A0|X_J,  "",     0,        "\"%s\"" },
  90. { C_STR,     X_A0|X_JL, "",     0,        "\"%s\"" },
  91.     
  92. #ifdef A0_REFS
  93. { C_CELL,      X_A0,        "",     0,        "$%s$%u" },
  94. { C_CELL,      X_A0,        "",     0,        "$%s%u" },
  95. { C_CELL,      X_A0,        "",     0,        "%s$%u" },
  96. { C_CELL,      X_A0,        "",     0,        "%s%u" },
  97. { C_RANGE,      X_A0,        "",     0,        "$%s$%u:$%s$%u" },
  98. { C_RANGE,      X_A0,        "",     0,        "$%s%u:$%s$%u" },
  99. { C_RANGE,      X_A0,        "",     0,        "$%s$%u:$%s%u" },
  100. { C_RANGE,      X_A0,        "",     0,        "$%s%u:$%s%u" },
  101. { C_RANGE,      X_A0,        "",     0,        "%s$%u:$%s$%u" },
  102. { C_RANGE,      X_A0,        "",     0,        "%s%u:$%s$%u" },
  103. { C_RANGE,      X_A0,        "",     0,        "%s$%u:$%s%u" },
  104. { C_RANGE,      X_A0,        "",     0,        "%s%u:$%s%u" },
  105. { C_RANGE,      X_A0,        "",     0,        "$%s$%u:%s$%u" },
  106. { C_RANGE,      X_A0,        "",     0,        "$%s%u:%s$%u" },
  107. { C_RANGE,      X_A0,        "",     0,        "$%s$%u:%s%u" },
  108. { C_RANGE,      X_A0,        "",     0,        "$%s%u:%s%u" },
  109. { C_RANGE,      X_A0,        "",     0,        "%s$%u:%s$%u" },
  110. { C_RANGE,      X_A0,        "",     0,        "%s%u:%s$%u" },
  111. { C_RANGE,      X_A0,        "",     0,        "%s$%u:%s%u" },
  112. { C_RANGE,      X_A0,        "",     0,        "%s%u:%s%u" },
  113. #else
  114. { C_CELL,      X_A0,        "",     0,        "r%uc%u" },
  115. { C_CELL,      X_A0,        "",     0,        "r[%+d]c%u" },
  116. { C_CELL,      X_A0,        "",     0,        "r%uc[%+d]" },
  117. { C_CELL,      X_A0,        "",     0,        "r[%+d]c[%+d]" },
  118. { C_RANGE,      X_A0,        "",     0,        "r%u:%uc%u:%u" },
  119. { C_RANGE,      X_A0,        "",     0,        "r[%+d]:%uc%u:%u" },
  120. { C_RANGE,      X_A0,        "",     0,        "r%u:[%+d]c%u:%u" },
  121. { C_RANGE,      X_A0,        "",     0,        "r[%+d]:[%+d]c%u:%u" },
  122. { C_RANGE,      X_A0,        "",     0,        "r%u:%uc[%+d]:%u" },
  123. { C_RANGE,      X_A0,        "",     0,        "r[%+d]:%uc[%+d]:%u" },
  124. { C_RANGE,      X_A0,        "",     0,        "r%u:[%+d]c[%+d]:%u" },
  125. { C_RANGE,      X_A0,        "",     0,        "r[%+d]:[%+d]c[%+d]:%u" },
  126. { C_RANGE,      X_A0,        "",     0,        "r%u:%uc%u:[%+d]" },
  127. { C_RANGE,      X_A0,        "",     0,        "r[%+d]:%uc%u:[%+d]" },
  128. { C_RANGE,      X_A0,        "",     0,        "r%u:[%+d]c%u:[%+d]" },
  129. { C_RANGE,      X_A0,        "",     0,        "r[%+d]:[%+d]c%u:[%+d]" },
  130. { C_RANGE,      X_A0,        "",     0,        "r%u:%uc[%+d]:[%+d]" },
  131. { C_RANGE,      X_A0,        "",     0,        "r[%+d]:%uc[%+d]:[%+d]" },
  132. { C_RANGE,      X_A0,        "",     0,        "r%u:[%+d]c[%+d]:[%+d]" },
  133. { C_RANGE,      X_A0,        "",        0,        "r[%+d]:[%+d]c[%+d]:[%+d]" },
  134. #endif
  135.  
  136. { C_CONST,      X_A0,        "",     0,        tname },
  137. { C_CONST,      X_A0,        "",     0,        fname },
  138.  
  139. { C_CONST,      X_A0,        "",        0,        iname },
  140. { C_CONST,      X_A0,        "",        0,        mname },
  141. { C_CONST,      X_A0,        "",        0,        nname },
  142. { C_ERR,      X_A0|X_J, "",        0,        "%s" },
  143. { C_FLT,      X_A0,        "",        0,        "%.15g" },
  144. { C_INT,      X_A0,        "",        0,        "%ld" },
  145.  
  146. { C_VAR,      X_A0,        "",        0,        "%s" },
  147.  
  148. { C_UNA,      X_A1,        "F",    0,        "-" },
  149. { C_UNA,      X_A1,        "B",    0,        "!" },
  150.  
  151. { C_INF|L|INF(6), X_A2,     "NN",   0,        "-" },
  152. { C_INF|L|INF(7), X_A2,        "NN",   0,        "/" },
  153. { C_INF|L|INF(7), X_A2,        "NN",   0,        "%" },
  154. { C_INF|L|INF(7), X_A2,        "NN",   0,        "*" },
  155. { C_INF|L|INF(6), X_A2,        "NN",   0,        "+" },
  156. { C_INF|L|INF(2), X_A2,        "SS",   0,        "&" },
  157. { C_INF|N|INF(4), X_A2,        "AA",   0,        "=" },
  158. { C_INF|N|INF(5), X_A2,        "AA",   0,        ">=" },
  159. { C_INF|N|INF(5), X_A2,        "AA",   0,        ">" },
  160. { C_INF|N|INF(5), X_A2,        "AA",   0,        "<" },
  161. { C_INF|N|INF(5), X_A2,        "AA",   0,        "<=" },
  162. { C_INF|N|INF(4), X_A2,        "AA",   0,        "!=" },
  163. { C_INF|R|INF(8), X_A2,        "FF",   V pow,    "^" },
  164.  
  165. { C_FN0,      X_A0,        "",     0,        "pi" },
  166. { C_FN0X,      X_A0,        "",     0,        "row" },
  167. { C_FN0X,      X_A0,        "",     0,        "col" },
  168. { C_FN0|C_T,      X_A0,        "",     0,        "now" },
  169.  
  170. { C_FN1,      X_A1,        "F",    V fabs,    "abs" },
  171. { C_FN1,      X_A1,        "F",    V acos,    "acos" },
  172. { C_FN1,      X_A1,        "F",    V asin,    "asin" },
  173. { C_FN1,      X_A1,        "F",    V atan,    "atan" },
  174. { C_FN1,      X_A1,        "F",    V ceil,    "ceil" },
  175. { C_FN1,      X_A1,        "F",    V to_int,    "int" },
  176. { C_FN1,      X_A1,        "F",    V floor,    "floor" },
  177. { C_FN1,      X_A1,        "F",    V cos,    "cos" },
  178. { C_FN1,      X_A1,        "F",    V dtr,    "dtr" },
  179. { C_FN1,      X_A1,        "F",    V exp,    "exp" },
  180. { C_FN1,      X_A1,        "F",    V log,    "log" },
  181. { C_FN1,      X_A1,        "F",    V log10,    "log10" },
  182. { C_FN1,      X_A1,        "F",    V rtd,    "rtd" },
  183. { C_FN1,      X_A1,        "F",    V sin,    "sin" },
  184. { C_FN1,      X_A1,        "F",    V sqrt,    "sqrt" },
  185. { C_FN1,      X_A1,        "F",    V tan,    "tan" },
  186. { C_FN1,      X_A1,        "I",    0,        "ctime" },
  187. { C_FN1,      X_A1,        "A",    0,        "negate" },
  188. { C_FN1,      X_A1,        "A",    0,        "not" },
  189. { C_FN1,      X_A1,        "A",    0,        "iserr" },
  190. { C_FN1,      X_A1,        "A",    0,        "isnum" },
  191.  
  192. { C_FN1|C_T,      X_A1,        "I",    0,        "rnd" },
  193. { C_FN1,      X_A1,        "R",    0,        "rows" },
  194. { C_FN1,      X_A1,        "R",    0,        "cols" },
  195. { C_FN2,      X_A2,        "FF",   V atan2,    "atan2" },
  196. { C_FN2,      X_A2,        "FF",   V hypot,    "hypot" },
  197. { C_FN2,      X_A2,        "FI",   0,        "fixed" },
  198. { C_FN2,      X_A2,        "AA",   0,        "iferr" },
  199. { C_FN2,      X_A2,        "RI",   0,        "index" },
  200. { C_FN3,      X_A3,        "RII",  0,        "index" },
  201. { C_FNN,      X_AN,        "IAAA", 0,        "oneof" },
  202.  
  203. { C_FNN,      X_AN,        "SIIA", 0,        "file" },
  204. { C_FNN,      X_AN,        "EEEE", 0,        "sum" },
  205. { C_FNN,      X_AN,        "EEEE", 0,        "prod" },
  206. { C_FNN,      X_AN,        "EEEE", 0,        "avg" },
  207. { C_FNN,      X_AN,        "EEEE", 0,        "std" },
  208. { C_FNN,      X_AN,        "EEEE", 0,        "max" },
  209. { C_FNN,      X_AN,        "EEEE", 0,        "min" },
  210. { C_FNN,      X_AN,        "EEEE", 0,        "count" },
  211. { C_FNN,      X_AN,        "EEEE", 0,        "var" },
  212.  
  213. };
  214.  
  215. #ifdef USE_DLD
  216. int n_usr_funs;
  217. struct function **usr_funs;
  218. int *usr_n_funs;
  219. #else
  220. int n_usr_funs = 3;
  221. extern struct function busi_funs[];
  222. extern struct function string_funs[];
  223. extern struct function cells_funs[];
  224.  
  225. static struct function *__usr_funs[] = {
  226.     busi_funs,
  227.     string_funs,
  228.     cells_funs,
  229. };
  230. static int __usr_n_funs[] = {
  231.     18,    11,    10
  232. };
  233.  
  234. struct function **usr_funs = __usr_funs;
  235. int *usr_n_funs = __usr_n_funs;
  236. #endif
  237.  
  238. /* ... A whole huge empty space, then ... */
  239. struct function skip_funs[] = {
  240. { C_SKIP,    X_A0|X_J,  "",        0,    "<Skip %u>" },
  241. { C_SKIP,    X_A0|X_JL, "",        0,    "<SkipL %u>" },
  242. };
  243.  
  244. /* The memory allocated here is used for several things, but byte_compile
  245.    is a small file, so it might as well be here */
  246. void
  247. init_mem FUN0()
  248. {
  249.     int n;
  250.     extern VOIDSTAR hash_new();
  251.  
  252.     parse_hash=hash_new();
  253.     hash_insert(parse_hash,the_funs[F_IF].fn_str,&the_funs[F_IF]);
  254.     hash_insert(parse_hash,the_funs[AND].fn_str,&the_funs[AND]);
  255.     hash_insert(parse_hash,the_funs[OR].fn_str,&the_funs[OR]);
  256.     for(n=F_PI;n<USR1;n++)
  257.         hash_insert(parse_hash,the_funs[n].fn_str,&the_funs[n]);
  258. #ifndef USE_DLD
  259.     for(n=0;n<n_usr_funs;n++) {
  260.         int nn;
  261.  
  262.         for(nn=0;usr_funs[n][nn].fn_str;nn++)
  263.             hash_insert(parse_hash,usr_funs[n][nn].fn_str,&usr_funs[n][nn]);
  264. #ifdef TEST
  265.         if(usr_n_funs[n]!=nn) {
  266.             fprintf(stderr,"Usr_n_funs[%d]%d!=%d",n,usr_n_funs[n],nn);
  267.             usr_n_funs[n]=nn;
  268.             
  269.         }
  270. #endif
  271.     }
  272. #endif
  273.     fn_stack=init_stack();
  274.     str_stack=init_stack();
  275.     obstack_begin(&tmp_mem,400);
  276.     tmp_mem_start=obstack_alloc(&tmp_mem,0);
  277. }
  278.  
  279. #ifdef USE_DLD
  280. void
  281. add_usr_funs FUN1(struct function *,new_funs)
  282. {
  283.     int n;
  284.  
  285.     n_usr_funs++;
  286.  
  287.     usr_funs=usr_funs ? ck_realloc(usr_funs,n_usr_funs*sizeof(struct function *)) : ck_malloc(sizeof(struct function *));
  288.  
  289.     usr_n_funs = usr_n_funs ? ck_realloc(usr_n_funs,n_usr_funs*sizeof(int)) : ck_malloc(sizeof(int));
  290.  
  291.     usr_funs[n_usr_funs-1]=new_funs;
  292.     for(n=0;new_funs[n].fn_str;n++)
  293.         hash_insert(parse_hash,new_funs[n].fn_str,&new_funs[n]);
  294.     usr_n_funs[n_usr_funs-1]=n;
  295. }
  296. #endif
  297.  
  298. /* Stash away a backpatch for future editing. */
  299. static void
  300. add_backpatch FUN2(unsigned, from,unsigned, to)
  301. {
  302.     if(!patches) {
  303.         patches_allocated=5;
  304.         patches=(struct backpatch *)ck_malloc(patches_allocated*sizeof(struct backpatch));
  305.         patches_used=0;
  306.     }
  307.     if(patches_allocated==patches_used) {
  308.         patches_allocated*=2;
  309.  
  310.         patches=(struct backpatch *)ck_realloc(patches,patches_allocated*sizeof(struct backpatch));
  311.     }
  312.     patches[patches_used].from=from;
  313.     patches[patches_used].to=to;
  314.     patches_used++;
  315. }
  316.  
  317. static int
  318. cmp_patch FUN2(int,n1, int,n2)
  319. {
  320.     int ret;
  321.  
  322.     ret=(patches[n1].from == patches[n2].from) ? patches[n1].to-patches[n2].to : patches[n1].from - patches[n2].from;
  323.     return ret;
  324. }
  325.  
  326. static void
  327. swp_patch FUN2(int,n1, int,n2)
  328. {
  329.     struct backpatch tmp;
  330.  
  331.     tmp=patches[n1];
  332.     patches[n1]=patches[n2];
  333.     patches[n2]=tmp;
  334. }
  335.  
  336. static void
  337. rot_patch FUN2(int,n1, int,n2)
  338. {
  339.     struct backpatch tmp;
  340.     tmp=patches[n2];
  341.     while(n2>n1) {
  342.         patches[n2]=patches[n2-1];
  343.         --n2;
  344.     }
  345.     patches[n2]=tmp;
  346. }
  347.     
  348.  
  349. /* This takes an ascii string and returns a pointer to the byte-compiled
  350.    result.  It calls yyparse() to do the actual parsing.  This is complicated
  351.    only because yyparse returns a parse tree which needs to be turned into
  352.    postfix compiled bytes.  This is further complicated by the presence of
  353.    forward branches in the byte-compiled code.  That's what the backpatch
  354.    stuff is for.
  355.    
  356.    It'd be nice if oneof() could compile into
  357.    arg1
  358.    ONEOF n_possibilities
  359.    JUMP poss1
  360.    JUMP poss2
  361.    JUMP poss3
  362.    ...
  363.    JUMP error
  364.    {poss 1}
  365.    JUMP end
  366.    {poss 2}
  367.    JUMP end
  368.    ...
  369.    end: {rest of expression}
  370.    instead of the simplistic (and slow-to-execute) version currently used
  371.  
  372.    It'd also be nice if byte-compiled expressions could have *BIG*
  373.    subexpressions, instead of silently failing as they do now.  Error checking
  374.    and a way to encode longer branches would be a *good* idea.
  375.  */
  376. unsigned char *
  377. parse_and_compile FUN1(char *,string)
  378. {
  379.     struct node *new_node;
  380.     struct node *node;
  381.     struct function *f;
  382.     unsigned char *ret;
  383.     int n;
  384.     unsigned buf_siz;
  385.     int need_relax;
  386.     int byte;
  387.  
  388.     extern int yyparse EXT0();
  389.     extern char *instr;
  390.     extern int parse_error;
  391.     extern struct node *parse_return;
  392.  
  393.     instr=string;
  394.     parse_error=0;
  395.     patches_used=0;
  396.     if(yyparse() || parse_error) {
  397.         ret=ck_malloc(strlen(string)+5);
  398.         ret[0]=CONST_ERR;
  399.         ret[1]=2;
  400.         ret[2]=parse_error;
  401.         ret[3]=ENDCOMP;
  402.         strcpy((char *)&ret[4],string);
  403.         (void)obstack_free(&tmp_mem,tmp_mem_start);
  404.         return ret;
  405.     }
  406.  
  407.     node=parse_return;
  408.     if(!node)
  409.         return 0;
  410.  
  411.  loop:
  412.      if(node->comp_value<USR1) {
  413.         f= &the_funs[node->comp_value];
  414.         byte=node->comp_value;
  415.     } else if(node->comp_value<SKIP) {
  416.         n=node->sub_value;
  417.         f= &usr_funs[node->comp_value-USR1][n];
  418.         /* Wait until this has no subrs left. . . */
  419.         if(!node->n_x.v_subs[0] && !node->n_x.v_subs[1])
  420.             (void)obstack_1grow(&tmp_mem,(int)node->comp_value);
  421.         /* Cheat */
  422.         byte=node->sub_value;
  423.     } else {
  424.         f= &skip_funs[node->comp_value-SKIP];
  425.         byte=node->comp_value;
  426.     }
  427.  
  428. #ifdef TEST
  429.     if(!f)
  430.         panic("f is zero in byte_compile!");
  431. #endif
  432.     switch(GET_COMP(f->fn_comptype)) {
  433.     case C_IF:
  434.         /* if compiles to
  435.            test-code IF amt-to-skip-on-false true-code SKIP
  436.                amt-to-skip-on-true false-code */
  437.         if(node->n_x.v_subs[0]) {
  438.             if(node->n_x.v_subs[0]->n_x.v_subs[0]) {
  439.                 /* Put out the test-code */
  440.                 push_stack(fn_stack,node);
  441.                 new_node=node->n_x.v_subs[0]->n_x.v_subs[0];
  442.                 node->n_x.v_subs[0]->n_x.v_subs[0]=0;
  443.                 node=new_node;
  444.                 goto loop;
  445.             }
  446.             /* Put out IF, null-byte to backpatch */
  447.             (void)obstack_1grow(&tmp_mem,byte);
  448.             node->add_byte=obstack_object_size(&tmp_mem);
  449.             (void)obstack_1grow(&tmp_mem,0);
  450.  
  451.             /* put out true-code */
  452.             push_stack(fn_stack,node);
  453.             new_node=node->n_x.v_subs[0]->n_x.v_subs[1];
  454.             node->n_x.v_subs[0]=0;
  455.             node=new_node;
  456.             goto loop;
  457.         }
  458.         if(node->n_x.v_subs[1]) {
  459.  
  460.             (void)obstack_1grow(&tmp_mem,SKIP);
  461.             (void)obstack_1grow(&tmp_mem,0);
  462.             add_backpatch(node->add_byte,obstack_object_size(&tmp_mem));
  463.             node->add_byte=obstack_object_size(&tmp_mem)-1;
  464.  
  465.             push_stack(fn_stack,node);
  466.             new_node=node->n_x.v_subs[1];
  467.             node->n_x.v_subs[1]=0;
  468.             node=new_node;
  469.             goto loop;
  470.         }
  471.         add_backpatch(node->add_byte,obstack_object_size(&tmp_mem));
  472.         break;
  473.  
  474.     case C_ANDOR:
  475.         if(node->n_x.v_subs[0]) {
  476.             push_stack(fn_stack,node);
  477.             new_node=node->n_x.v_subs[0];
  478.             node->n_x.v_subs[0]=0;
  479.             node=new_node;
  480.             goto loop;
  481.         }
  482.         if(node->n_x.v_subs[1]) {
  483.             (void)obstack_1grow(&tmp_mem,byte);
  484.             node->add_byte=obstack_object_size(&tmp_mem);
  485.             (void)obstack_1grow(&tmp_mem,0);    /* for backpatching */
  486.             push_stack(fn_stack,node);
  487.             new_node=node->n_x.v_subs[1];
  488.             node->n_x.v_subs[1]=0;
  489.             node=new_node;
  490.             goto loop;
  491.         }
  492.         add_backpatch(node->add_byte,obstack_object_size(&tmp_mem));
  493.         break;
  494.  
  495.     case C_ERR:
  496.         (void)obstack_1grow(&tmp_mem,byte);
  497.         node->add_byte=obstack_object_size(&tmp_mem);
  498.         (void)obstack_1grow(&tmp_mem,0);
  499.         (void)obstack_1grow(&tmp_mem,node->n_x.v_int);
  500.         node->n_x.v_string=ename[node->n_x.v_int];
  501.         push_stack(str_stack,node);
  502.         break;
  503.  
  504.     case C_FLT:
  505.         (void)obstack_1grow(&tmp_mem,byte);
  506.         (void)obstack_grow(&tmp_mem,&(node->n_x.v_float),sizeof(double));
  507.         break;
  508.  
  509.     case C_INT:
  510.         (void)obstack_1grow(&tmp_mem,byte);
  511.         (void)obstack_grow(&tmp_mem,&(node->n_x.v_int),sizeof(long));
  512.         break;
  513.  
  514.     case C_STR:
  515.         (void)obstack_1grow(&tmp_mem,byte);
  516.         node->add_byte=obstack_object_size(&tmp_mem);
  517.         (void)obstack_1grow(&tmp_mem,0);
  518.         push_stack(str_stack,node);
  519.         break;
  520.  
  521.     case C_VAR:
  522.         add_ref_to(obstack_object_size(&tmp_mem));
  523.         add_var_ref(node->n_x.v_var);
  524.         (void)obstack_1grow(&tmp_mem,byte);
  525.         (void)obstack_grow(&tmp_mem,&(node->n_x.v_var),sizeof(struct var *));
  526.         break;
  527.  
  528.     case C_CELL:
  529.         add_ref_to(obstack_object_size(&tmp_mem));
  530.         add_ref(node->n_x.v_rng.lr,node->n_x.v_rng.lc);
  531.         (void)obstack_1grow(&tmp_mem,byte);
  532. #if BITS_PER_CELLREF==16
  533.         (void)obstack_1grow(&tmp_mem,node->n_x.v_rng.lr>>8);
  534.         (void)obstack_1grow(&tmp_mem,node->n_x.v_rng.lr);
  535.         (void)obstack_1grow(&tmp_mem,node->n_x.v_rng.lc>>8);
  536.         (void)obstack_1grow(&tmp_mem,node->n_x.v_rng.lc);
  537. #else
  538. #if BITS_PER_CELLREF==8
  539.         (void)obstack_1grow(&tmp_mem,node->n_x.v_rng.lr);
  540.         (void)obstack_1grow(&tmp_mem,node->n_x.v_rng.lc);
  541. #else
  542.         Insert appropriate code here
  543. #endif
  544. #endif
  545.         break;
  546.  
  547.     case C_RANGE:
  548.         add_ref_to(obstack_object_size(&tmp_mem));
  549.         add_range_ref(&(node->n_x.v_rng));
  550.         (void)obstack_1grow(&tmp_mem,byte);
  551.         (void)obstack_grow(&tmp_mem,&(node->n_x.v_rng),sizeof(struct rng));
  552.         break;
  553.  
  554.     case C_FN0:
  555.     case C_CONST:
  556.         if(f->fn_comptype&C_T)
  557.             add_timer_ref(obstack_object_size(&tmp_mem));
  558.         (void)obstack_1grow(&tmp_mem,byte);
  559.         break;
  560.  
  561.     case C_FN0X:
  562.         add_ref_to(obstack_object_size(&tmp_mem));
  563.         (void)obstack_1grow(&tmp_mem,byte);
  564.         break;
  565.  
  566.     case C_FN1:
  567.     case C_UNA:
  568.         if(node->n_x.v_subs[0]) {
  569.             push_stack(fn_stack,node);
  570.             new_node=node->n_x.v_subs[0];
  571.             node->n_x.v_subs[0]=0;
  572.             node=new_node;
  573.             goto loop;
  574.         }
  575.         if(f->fn_comptype&C_T)
  576.             add_timer_ref(obstack_object_size(&tmp_mem));
  577.         (void)obstack_1grow(&tmp_mem,byte);
  578.         break;
  579.  
  580.     case C_FN2:
  581.     case C_INF:
  582.         if(node->n_x.v_subs[0]) {
  583.             push_stack(fn_stack,node);
  584.             new_node=node->n_x.v_subs[0];
  585.             node->n_x.v_subs[0]=0;
  586.             node=new_node;
  587.             goto loop;
  588.         }
  589.         if(node->n_x.v_subs[1]) {
  590.             push_stack(fn_stack,node);
  591.             new_node=node->n_x.v_subs[1];
  592.             node->n_x.v_subs[1]=0;
  593.             node=new_node;
  594.             goto loop;
  595.         }
  596.         (void)obstack_1grow(&tmp_mem,byte);
  597.         break;
  598.  
  599.     case C_FN3:
  600.         if(node->n_x.v_subs[0]) {
  601.             if(node->n_x.v_subs[0]->n_x.v_subs[0]) {
  602.                 push_stack(fn_stack,node);
  603.                 new_node=node->n_x.v_subs[0]->n_x.v_subs[0];
  604.                 node->n_x.v_subs[0]->n_x.v_subs[0]=0;
  605.                 node=new_node;
  606.                 goto loop;
  607.             }
  608.             push_stack(fn_stack,node);
  609.             new_node=node->n_x.v_subs[0]->n_x.v_subs[1];
  610.             node->n_x.v_subs[0]=0;
  611.             node=new_node;
  612.             goto loop;
  613.         }
  614.         if(node->n_x.v_subs[1]) {
  615.             push_stack(fn_stack,node);
  616.             new_node=node->n_x.v_subs[1];
  617.             node->n_x.v_subs[1]=0;
  618.             node=new_node;
  619.             goto loop;
  620.         }
  621.         if(f->fn_comptype&C_T)
  622.             add_timer_ref(obstack_object_size(&tmp_mem));
  623.         (void)obstack_1grow(&tmp_mem,byte);
  624.         break;
  625.  
  626.     case C_FN4:
  627.         if(node->n_x.v_subs[0]) {
  628.             if(node->n_x.v_subs[0]->n_x.v_subs[0]) {
  629.                 push_stack(fn_stack,node);
  630.                 new_node=node->n_x.v_subs[0]->n_x.v_subs[0];
  631.                 node->n_x.v_subs[0]->n_x.v_subs[0]=0;
  632.                 node=new_node;
  633.                 goto loop;
  634.             }
  635.             push_stack(fn_stack,node);
  636.             new_node=node->n_x.v_subs[0]->n_x.v_subs[1];
  637.             node->n_x.v_subs[0]=0;
  638.             node=new_node;
  639.             goto loop;
  640.         }
  641.         if(node->n_x.v_subs[1]) {
  642.             if(node->n_x.v_subs[1]->n_x.v_subs[0]) {
  643.                 push_stack(fn_stack,node);
  644.                 new_node=node->n_x.v_subs[1]->n_x.v_subs[0];
  645.                 node->n_x.v_subs[1]->n_x.v_subs[0]=0;
  646.                 node=new_node;
  647.                 goto loop;
  648.             }
  649.             push_stack(fn_stack,node);
  650.             new_node=node->n_x.v_subs[1]->n_x.v_subs[1];
  651.             node->n_x.v_subs[1]=0;
  652.             node=new_node;
  653.             goto loop;
  654.         }
  655.         if(f->fn_comptype&C_T)
  656.             add_timer_ref(obstack_object_size(&tmp_mem));
  657.         (void)obstack_1grow(&tmp_mem,byte);
  658.         break;
  659.  
  660.     case C_FNN:
  661.         if(node->n_x.v_subs[1]) {
  662.             if(node->add_byte==0)
  663.                 for(new_node=node;new_node->n_x.v_subs[1];new_node=new_node->n_x.v_subs[1])
  664.                     node->add_byte++;
  665.             for(new_node=node;new_node->n_x.v_subs[1]->n_x.v_subs[1];new_node=new_node->n_x.v_subs[1])
  666.                 ;
  667.             push_stack(fn_stack,node);
  668.             node=new_node->n_x.v_subs[1]->n_x.v_subs[0];
  669.             new_node->n_x.v_subs[1]=0;
  670.             goto loop;
  671.         }
  672.         (void)obstack_1grow(&tmp_mem,byte);
  673.         (void)obstack_1grow(&tmp_mem,node->add_byte);
  674.         break;
  675.  
  676.     default:
  677.         panic("Bad comptype %d",f->fn_comptype);
  678.     }
  679.     node=(struct node *)pop_stack(fn_stack);
  680.     if(node)
  681.         goto loop;
  682.  
  683.     (void)obstack_1grow(&tmp_mem,0);
  684.  
  685.     while(node=pop_stack(str_stack)) {
  686.         add_backpatch(node->add_byte,obstack_object_size(&tmp_mem));
  687.         (void)obstack_grow(&tmp_mem,node->n_x.v_string,strlen(node->n_x.v_string)+1);
  688.     }
  689.  
  690.     buf_siz=obstack_object_size(&tmp_mem);
  691.     ret=(unsigned char *)ck_malloc(buf_siz);
  692.     bcopy(obstack_finish(&tmp_mem),ret,buf_siz);
  693.  
  694.     need_relax=0;
  695.     for(n=0;n<patches_used;n++) {
  696.         long offset;
  697.  
  698.         offset=(patches[n].to-patches[n].from)-1;
  699.         if(offset<0 || offset>255)
  700.             need_relax++;
  701.         else
  702.             ret[patches[n].from]=offset;
  703.     }
  704.     if(need_relax) {
  705.         int n_lo;
  706.         long offset;
  707.         int start;
  708.         extern void sort();
  709.  
  710.             /* ... Sort the patches list ... */
  711.         sort(patches_used,cmp_patch,swp_patch,rot_patch);
  712.  
  713.         while(need_relax) {
  714.  
  715.             ret=ck_realloc(ret,buf_siz+need_relax);
  716.             for(n_lo=0;n_lo<patches_used;n_lo++) {
  717.                 offset=(patches[n_lo].to-patches[n_lo].from)-1;
  718.                 if(offset<0 || offset>255-need_relax)
  719.                     break;
  720.             }
  721.  
  722.             /* n_lo points to the first jump that may need to be relaxed */
  723.             for(n=n_lo;n<patches_used;n++) {
  724.                 offset=(patches[n].to-patches[n].from)-1;
  725.                 if(offset<0 || offset>255) {
  726.                     int nn;
  727.  
  728.                     start=patches[n].from;
  729.     
  730.                     ret[start-1]++;/* Translate insn to LONG */
  731.                     ret[start  ]=offset;
  732.                     bcopy(&ret[start+1],&ret[start+2],buf_siz-start);
  733.                     ret[start+1]=offset>>8;
  734.                     need_relax--;
  735.                     buf_siz++;
  736.                     for(nn=0;nn<patches_used;nn++) {
  737.                         if(patches[nn].from>start)
  738.                             patches[nn].from++;
  739.                         if(patches[nn].to>start)
  740.                             patches[nn].to++;
  741.                         if(patches[nn].from<start && patches[nn].to>start && ret[patches[nn].from]++==255) {
  742.                             if(ret[patches[nn].from-1]&01)
  743.                                 ret[patches[nn].from+1]++;
  744.                             else
  745.                                 need_relax++;
  746.                         }
  747.                     }
  748.                 }
  749.             }
  750.         }
  751.     }
  752.  
  753.     (void)obstack_free(&tmp_mem,tmp_mem_start);
  754.  
  755.     patches_used=0;
  756.  
  757.     return ret;
  758. }
  759.  
  760. /* Back when strings stored a char*, they needed to be freed when a
  761.    byte-compiled expression was freed.  Now that they're appended to the end,
  762.    they don't need to be specially freed anymore.
  763.  */
  764. void
  765. byte_free FUN1(unsigned char *,form)
  766. {
  767. /* no longer needed
  768.     unsigned char *f;
  769.  
  770.     for(f=form;*f;f++) {
  771.         switch(*f) {
  772.         case IF:
  773.         case F_IF:
  774.         case SKIP:
  775.         case AND:
  776.         case OR:
  777.         case CONST_STR:
  778.             f++;
  779.             break;
  780.         case CONST_INT:
  781.             f+=sizeof(long);
  782.             break;
  783.         case CONST_FLT:
  784.             f+=sizeof(double);
  785.             break;
  786.         case VAR:
  787.             f+=sizeof(struct var *);
  788.             break;
  789.         case R_CELL:
  790.         case R_CELL|ROWREL:
  791.         case R_CELL|COLREL:
  792.         case R_CELL|ROWREL|COLREL:
  793.             f+=EXP_ADD;
  794.             break;
  795.         case RANGE:
  796.         case RANGE|LRREL:
  797.         case RANGE|LRREL|LCREL:
  798.         case RANGE|LRREL|LCREL|HCREL:
  799.         case RANGE|LRREL|HCREL:
  800.         case RANGE|LRREL|HRREL:
  801.         case RANGE|LRREL|HRREL|LCREL:
  802.         case RANGE|LRREL|HRREL|LCREL|HCREL:
  803.         case RANGE|LRREL|HRREL|HCREL:
  804.         case RANGE|HRREL:
  805.         case RANGE|HRREL|LCREL:
  806.         case RANGE|HRREL|LCREL|HCREL:
  807.         case RANGE|HRREL|HCREL:
  808.         case RANGE|LCREL:
  809.         case RANGE|LCREL|HCREL:
  810.         case RANGE|HCREL:
  811.             f+=EXP_ADD_RNG;
  812.             break;
  813.         case F_PRINTF:
  814.         case F_CONCAT:
  815.         case F_ONEOF:
  816.         case F_STRSTR:
  817.         case F_EDIT:
  818.         case AREA_SUM:
  819.         case AREA_PROD:
  820.         case AREA_AVG:
  821.         case AREA_STD:
  822.         case AREA_MAX:
  823.         case AREA_MIN:
  824.         case AREA_CNT:
  825.         case AREA_VAR:
  826.             f++;
  827.             break;
  828.         default:
  829.             break;
  830.         }
  831.     } */
  832.     free(form);
  833. }
  834.  
  835. /* This tries to tell if a byte-compiled expression is a constant.  If it
  836.    is a constant, we can free it, and never try to recompute its value.
  837.    This returns non-zero if the expression is constant.*/
  838. int
  839. is_constant FUN1(unsigned char *,bytes)
  840. {
  841.     /* It's constant, but it's already been dealt with.
  842.        Pretend it isn't. */
  843.     if(!bytes)
  844.         return 0;
  845.  
  846.     switch(bytes[0]) {
  847.     case CONST_ERR:
  848.         return (bytes[3]==0 && !strcmp((char *)bytes+4,ename[bytes[2]]));
  849.     case CONST_INT:
  850.         return bytes[sizeof(long)+1]==ENDCOMP;
  851.     case CONST_FLT:
  852.         return bytes[sizeof(double)+1]==ENDCOMP;
  853.     case CONST_STR:
  854.         return bytes[2]==ENDCOMP;
  855.     case F_TRUE:
  856.     case F_FALSE:
  857.     case CONST_INF:
  858.     case CONST_NINF:
  859.     case CONST_NAN:
  860.         return bytes[1]==ENDCOMP;
  861.     default:
  862.         return 0;
  863.     }
  864. }
  865.